#![allow(dead_code)]

struct SizedLrn {}

impl SizedLrn {
    fn hello() {
        println!("Sized learnning!");
    }
}

#[cfg(test)]
mod tests {
    // use super::*;

    #[test]
    fn basic_sized() {
        {
            struct Foo<T>(T);
            // struct FooUse(Foo<[i32]>);  // Foo的T没有实现Sized

            #[derive(Debug)]
            // 借用T, 并且不确定大小, 需要生命后期
            struct Bar<'a, T: ?Sized>(&'a T);

            #[derive(Debug)]
            // Bar有生命周期
            struct BarUse<'a>(Bar<'a, [i32]>);

            let arr1 = [33, 45, 66];
            let _bar = Bar(&arr1);
            let bar_use = BarUse(Bar(&arr1));

            println!("{:?}", bar_use);
        }
        {
            #[derive(Debug)]
            struct Bar<T: ?Sized>(T);

            #[derive(Debug)]
            // NOTE: struct BarUse(Bar<[i32]>), 但是[i32]没法知道大小, 不能使用这样的结构. 需要借用[i32].
            // 借用, 需要注释生命周期
            struct BarUse<'a>(Bar<&'a [i32]>);

            let arr1: &[i32] = &[1, 2, 3];
            let bar = Bar(arr1);
            let bar_use = BarUse(bar);

            println!("{:?}", bar_use);
        }
        {
            #[derive(Debug)]
            struct Bar<T: ?Sized>(T);
            #[derive(Debug)]
            struct BarUse<T: ?Sized>(T);
            #[derive(Debug)]
            struct BarUseOther<T: ?Sized>(Bar<T>);

            let arr1 = [2, 3, 4];
            let bar = Bar(arr1);
            let bar_use = BarUse(bar);
            let bar_use_other = BarUseOther(Bar(arr1));

            println!("{:?}", arr1);
            // println!("{:?}", bar); Bar存在stack, 没有实现clone
            println!("{:?}", bar_use);
            println!("{:?}", bar_use_other);
        }
    }

    #[test]
    fn function_unsized() {
        /// NOTE: unsized type 两种: [T], str
        fn process_data<T: ?Sized + std::fmt::Debug>(data: &T) {
            println!("processing data, {}", std::any::type_name::<T>());
            println!("{:?}", data);
        }

        let vec = vec![1, 2, 3, 4, 5];
        let arr = &[1, 2, 3];
        let arr1: &[i32] = arr; // 需要注释类型,强制转换为DST
        let str = "hello";
        process_data(&vec); // Vec<i32> Sized
        process_data(arr1); // &[i32] Sized, [i32] Unsied 需要?Sized trait
        process_data(str); // &str Sized, str Unsied 需要?Sized trait
    }

    #[test]
    fn trait_sized() {
        trait Test {
            fn print_some(&self) {
                println!("print some");
            }
        }

        #[derive(Debug)]
        struct MyType1;
        #[derive(Debug)]
        struct MyType2;

        impl Test for MyType1 {
            fn print_some(&self) {
                println!("print some for MyType1: {:?}", self);
            }
        }
        impl Test for MyType2 {
            fn print_some(&self) {
                println!("print some for MyType2: {:?}", self);
            }
        }

        let my_type1 = MyType1;
        let my_type2 = MyType2;

        let mut vec_my_type: Vec<Box<dyn Test>> = Vec::new();
        vec_my_type.push(Box::new(my_type1));
        vec_my_type.push(Box::new(my_type2));

        for p in vec_my_type {
            p.print_some();
        }
    }
}
